🎖️GitЯра🎖️
scripts/build-appimage.sh 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 4.54 KB
T8b949e#!/usr/bin/env bash
T8b949e# Wraps the jpackage app-image produced by :desktopApp:packageReleaseAppImage
T8b949e# into a real Linux .AppImage.
T8b949e#
T8b949e# Compose Multiplatform's TargetFormat.AppImage is jpackage's "app-image": an
T8b949e# unpacked application directory (bin/<App>, lib/...), NOT the single-file
T8b949e# AppImage bundle format. This script builds the AppDir scaffolding (AppRun,
T8b949e# .desktop entry, icon) around that directory and packs it with appimagetool.
T8b949e#
T8b949e# The output lands in main-release/appimage/ so the existing release upload
T8b949e# and attestation globs (main-release/*/*.AppImage) pick it up unchanged.
T8b949e#
T8b949e# Expects to run on a Linux host of the target architecture (x86_64/aarch64)
T8b949e# with APP_VERSION_NAME set (e.g. 2.8.0). appimagetool and the AppImage
T8b949e# runtime are downloaded pinned by version AND sha256 — bump the four hashes
T8b949e# together with the version pins below.
Tffa657set -euo pipefail
Te6edf3VERSIONTff7b72=Ta5d6ff"Tffd700${Te6edf3APP_VERSION_NAMETb4b4b4:Tb4b4b4?APP_VERSION_NAME must be set (e.g. 2.8.0)Tffd700}Ta5d6ff"
Te6edf3BINARIES_DIRTff7b72=Ta5d6ff"Tffd700${Te6edf3BINARIES_DIRTff7b72:-Te6edf3desktopAppTb4b4b4/build/compose/binaries/main-releaseTffd700}Ta5d6ff"
Te6edf3APPIMAGETOOL_VERSIONTff7b72=Ta5d6ff"1.9.1"
Te6edf3RUNTIME_VERSIONTff7b72=Ta5d6ff"20251108"
Te6edf3ARCHTff7b72=Ta5d6ff"Tff7b72$(uname -mTff7b72)Ta5d6ff"
Tff7b72case Ta5d6ff"Te6edf3$ARCHTa5d6ff" Tff7b72in
x86_64Tff7b72)
Te6edf3APPIMAGETOOL_SHA256Tff7b72=Ta5d6ff"ed4ce84f0d9caff66f50bcca6ff6f35aae54ce8135408b3fa33abfc3cb384eb0"
Te6edf3RUNTIME_SHA256Tff7b72=Ta5d6ff"2fca8b443c92510f1483a883f60061ad09b46b978b2631c807cd873a47ec260d"
Tb4b4b4;Tb4b4b4;
aarch64Tff7b72)
Te6edf3APPIMAGETOOL_SHA256Tff7b72=Ta5d6ff"f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158"
Te6edf3RUNTIME_SHA256Tff7b72=Ta5d6ff"00cbdfcf917cc6c0ff6d3347d59e0ca1f7f45a6df1a428a0d6d8a78664d87444"
Tb4b4b4;Tb4b4b4;
*Tff7b72)
Tffa657echo Ta5d6ff"Ta5d6ff::error::Unsupported architecture for AppImage: Tffd700${Te6edf3ARCHTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tb4b4b4;Tb4b4b4;
Tff7b72esac
T8b949e# --- Locate the jpackage app-image (directory name = CMP packageName; may contain spaces) ---
Te6edf3app_dirTff7b72=Ta5d6ff""
Te6edf3countTff7b72=T79c0ff0
Tff7b72for d Tff7b72in Ta5d6ff"Tffd700${Te6edf3BINARIES_DIRTffd700}Ta5d6ff/appTa5d6ff"/*/Tb4b4b4; Tff7b72do
Tff7b72[ -d Ta5d6ff"Te6edf3$dTa5d6ff" Tff7b72] Tff7b72|| Tff7b72continue
Te6edf3app_dirTff7b72=Ta5d6ff"Tffd700${Te6edf3dTb4b4b4%/Tffd700}Ta5d6ff"
Te6edf3countTff7b72=Tff7b72$((Te6edf3count Tff7b72+ T79c0ff1Tff7b72))
Tff7b72done
Tff7b72if Tff7b72[ Ta5d6ff"Te6edf3$countTa5d6ff" -ne T79c0ff1 Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ff::error::Expected exactly one app-image directory under Tffd700${Te6edf3BINARIES_DIRTffd700}Ta5d6ff/app, found Tffd700${Te6edf3countTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Te6edf3app_nameTff7b72=Ta5d6ff"Tff7b72$(basename Ta5d6ff"Te6edf3$app_dirTa5d6ff"Tff7b72)Ta5d6ff"
Te6edf3launcherTff7b72=Ta5d6ff"Tffd700${Te6edf3app_dirTffd700}Ta5d6ff/bin/Tffd700${Te6edf3app_nameTffd700}Ta5d6ff"
Tff7b72if Tff7b72[ ! -x Ta5d6ff"Te6edf3$launcherTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"Ta5d6ff::error::jpackage launcher not found or not executable: Tffd700${Te6edf3launcherTffd700}Ta5d6ff" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
Te6edf3iconTff7b72=Ta5d6ff"Tffd700${Te6edf3app_dirTffd700}Ta5d6ff/lib/Tffd700${Te6edf3app_nameTffd700}Ta5d6ff.pngTa5d6ff"
Tff7b72if Tff7b72[ ! -f Ta5d6ff"Te6edf3$iconTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
T8b949e# jpackage normally drops the icon at lib/<AppName>.png; fall back to the source icon.
Te6edf3iconTff7b72=Ta5d6ff"desktopApp/src/main/resources/icon.png"
Tff7b72fi
Tff7b72if Tff7b72[ ! -f Ta5d6ff"Te6edf3$iconTa5d6ff" Tff7b72]Tb4b4b4; Tff7b72then
Tffa657echo Ta5d6ff"::error::No icon found for the AppImage (looked in lib/ and desktopApp resources)" >Tb4b4b4&T79c0ff2
Tffa657exit T79c0ff1
Tff7b72fi
T8b949e# Desktop-entry id / output-name slug: "Meshtastic Desktop" -> meshtastic-desktop
Te6edf3slugTff7b72=Ta5d6ff"Tff7b72$(Tffa657printf Ta5d6ff'%s' Ta5d6ff"Te6edf3$app_nameTa5d6ff" Tb4b4b4| tr Ta5d6ff'[:upper:]' Ta5d6ff'[:lower:]' Tb4b4b4| tr Ta5d6ff' ' Ta5d6ff'-'Tff7b72)Ta5d6ff"
T8b949e# --- Assemble the AppDir ---
Te6edf3out_dirTff7b72=Ta5d6ff"Tffd700${Te6edf3BINARIES_DIRTffd700}Ta5d6ff/appimageTa5d6ff"
Te6edf3appdirTff7b72=Ta5d6ff"Tffd700${Te6edf3out_dirTffd700}Ta5d6ff/Tffd700${Te6edf3slugTffd700}Ta5d6ff.AppDirTa5d6ff"
rm -rf Ta5d6ff"Te6edf3$appdirTa5d6ff"
mkdir -p Ta5d6ff"Te6edf3$appdirTa5d6ff"
cp -a Ta5d6ff"Tffd700${Te6edf3app_dirTffd700}Ta5d6ff/.Ta5d6ff" Ta5d6ff"Te6edf3$appdirTa5d6ff/Ta5d6ff"
cat > Ta5d6ff"Tffd700${Te6edf3appdirTffd700}Ta5d6ff/AppRunTa5d6ff" Ta5d6ff<<EOF
HERE="\$(dirname "\$(readlink -f "\$0")")"
exec "\$HERE/bin/${app_name}" "\$@"
EOF
chmod +x Ta5d6ff"Tffd700${Te6edf3appdirTffd700}Ta5d6ff/AppRunTa5d6ff"
cp Ta5d6ff"Te6edf3$iconTa5d6ff" Ta5d6ff"Tffd700${Te6edf3appdirTffd700}Ta5d6ff/Tffd700${Te6edf3slugTffd700}Ta5d6ff.pngTa5d6ff"
cat > Ta5d6ff"Tffd700${Te6edf3appdirTffd700}Ta5d6ff/Tffd700${Te6edf3slugTffd700}Ta5d6ff.desktopTa5d6ff" Ta5d6ff<<EOF
[Desktop Entry]
Type=Application
Name=${app_name}
Exec=AppRun
Icon=${slug}
Comment=Meshtastic Desktop Application
Categories=Network;
Terminal=false
EOF
T8b949e# --- Fetch pinned appimagetool + runtime and pack ---
Te6edf3tools_dirTff7b72=Ta5d6ff"Tff7b72$(mktemp -dTff7b72)Ta5d6ff"
Tffa657trap Ta5d6ff'rm -rf "$tools_dir"' EXIT
curl -fsSL --retry T79c0ff5 --retry-delay T79c0ff10 --connect-timeout T79c0ff10 --max-time T79c0ff300 -o Ta5d6ff"Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/appimagetoolTa5d6ff" Tffea00\
Ta5d6ff"Ta5d6ffhttps://github.com/AppImage/appimagetool/releases/download/Tffd700${Te6edf3APPIMAGETOOL_VERSIONTffd700}Ta5d6ff/appimagetool-Tffd700${Te6edf3ARCHTffd700}Ta5d6ff.AppImageTa5d6ff"
Tffa657echo Ta5d6ff"Tffd700${Te6edf3APPIMAGETOOL_SHA256Tffd700}Ta5d6ff Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/appimagetoolTa5d6ff" Tb4b4b4| sha256sum -c -
chmod +x Ta5d6ff"Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/appimagetoolTa5d6ff"
curl -fsSL --retry T79c0ff5 --retry-delay T79c0ff10 --connect-timeout T79c0ff10 --max-time T79c0ff300 -o Ta5d6ff"Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/runtimeTa5d6ff" Tffea00\
Ta5d6ff"Ta5d6ffhttps://github.com/AppImage/type2-runtime/releases/download/Tffd700${Te6edf3RUNTIME_VERSIONTffd700}Ta5d6ff/runtime-Tffd700${Te6edf3ARCHTffd700}Ta5d6ff"
Tffa657echo Ta5d6ff"Tffd700${Te6edf3RUNTIME_SHA256Tffd700}Ta5d6ff Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/runtimeTa5d6ff" Tb4b4b4| sha256sum -c -
Te6edf3outputTff7b72=Ta5d6ff"Tffd700${Te6edf3out_dirTffd700}Ta5d6ff/Tffd700${Te6edf3app_nameTb4b4b4// /_Tffd700}Ta5d6ff-Tffd700${Te6edf3VERSIONTffd700}Ta5d6ff-Tffd700${Te6edf3ARCHTffd700}Ta5d6ff.AppImageTa5d6ff"
T8b949e# APPIMAGE_EXTRACT_AND_RUN: run appimagetool itself without FUSE.
T8b949e# --runtime-file: embed the pinned runtime instead of downloading `continuous`.
T8b949e# --no-appstream: we ship no AppStream metadata, skip that validation.
Te6edf3ARCHTff7b72=Ta5d6ff"Te6edf3$ARCHTa5d6ff" Te6edf3APPIMAGE_EXTRACT_AND_RUNTff7b72=T79c0ff1 Ta5d6ff"Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/appimagetoolTa5d6ff" Tffea00\
--no-appstream --runtime-file Ta5d6ff"Tffd700${Te6edf3tools_dirTffd700}Ta5d6ff/runtimeTa5d6ff" Tffea00\
Ta5d6ff"Te6edf3$appdirTa5d6ff" Ta5d6ff"Te6edf3$outputTa5d6ff"
T8b949e# Drop the AppDir so only the .AppImage remains for upload/attestation globs.
rm -rf Ta5d6ff"Te6edf3$appdirTa5d6ff"
Tffa657echo Ta5d6ff"Ta5d6ffBuilt Tff7b72$(du -h Ta5d6ff"Te6edf3$outputTa5d6ff" Tb4b4b4| cut -f1Tff7b72)Ta5d6ff AppImage: Tffd700${Te6edf3outputTffd700}Ta5d6ff"
Served by rngit 1.5.0 - Generated in 0.05s